﻿using Link_eLab.Domain.LayuiEntity;
using Link_eLab.Jwt.Dao;
using Link_eLab.Jwt.Entity;
using Link_eLab.JwtAuthorizePolicy.Enum;
using Link_eLab.JwtAuthorizePolicy.Extension;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Text;
using static Link_eLab.Helper.CryptHelper;

namespace Link_eLab.Jwt.Service.Impl
{
    /// <summary>
    /// 
    /// </summary>
    public class AuthService : IAuthService
    {
        private readonly IConfiguration Configuration;
        private readonly IHttpContextAccessor Accessor;
        private readonly IAdminDao AdminDao;
        private readonly IAdminRoleDao AdminRoleDao;
        private readonly IAdminRoleMenuDao AdminRoleMenuDao;
        private readonly ILogLoginDao LogLoginDao;
        private readonly IMenuDao MenuDao;

        #region 构造函数

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="configuration"></param>
        /// <param name="accessor"></param>
        /// <param name="adminDao"></param>
        /// <param name="adminRoleDao"></param>
        /// <param name="adminRoleMenuDao"></param>
        /// <param name="logLoginDao"></param>
        /// <param name="menuDao"></param>
        public AuthService(IConfiguration configuration,
            IHttpContextAccessor accessor,
            IAdminDao adminDao,
            IAdminRoleDao adminRoleDao,
            IAdminRoleMenuDao adminRoleMenuDao,
            ILogLoginDao logLoginDao,
            IMenuDao menuDao)
        {
            Configuration = configuration;
            Accessor = accessor;
            AdminDao = adminDao;
            AdminRoleDao = adminRoleDao;
            AdminRoleMenuDao = adminRoleMenuDao;
            LogLoginDao = logLoginDao;
            MenuDao = menuDao;
        }

        #endregion

        #region 用户登录

        /// <summary>
        /// 用户登录
        /// </summary>
        /// <param name="clientType">客户端</param>
        /// <param name="phone">电话号码</param>
        /// <param name="password">密码</param>
        /// <returns>JSON结果集</returns>
        public JsonResult AccessAuthorization(int clientType, string phone, string password)
        {
            var admin = AdminDao.QuerySingle(w => w.Phone.Equals(phone)).Result;

            if (admin == null)
            {
                return new JsonResult(new
                {
                    Code = 0,
                    Success = false,
                    Msg = "该用户不存在"
                });
            }

            AESCrypt aesCrypt = new AESCrypt();
            if (!password.Equals(aesCrypt.Decrypt(admin.PassWord)))
            {
                return new JsonResult(new
                {
                    Code = 0,
                    Success = false,
                    Msg = "用户名或密码错误，请重新登录。"
                });
            }

            if (admin.Disabled == 0)
            {
                return new JsonResult(new
                {
                    Code = 0,
                    Success = false,
                    Msg = "该用户已冻结，请联系管理员。"
                });
            }

            // 如果是基于用户的授权策略，这里要添加用户;如果是基于角色的授权策略，这里要添加角色
            var claims = new Claim[]
            {
                new Claim("clientType", clientType.ToString()),
                new Claim("userId", admin.ID),
                new Claim("orgId", admin.OrgGuid),
                new Claim("userName", admin.Name),
                new Claim("jti", Guid.NewGuid().ToString().ToUpper())
            };

            // 用户标识
            var identity = new ClaimsIdentity(JwtBearerDefaults.AuthenticationScheme);
            identity.AddClaims(claims);

            PermissionRequirement requirement = new PermissionRequirement(
                Configuration["Audience:Issuer"].ToString(),
                Configuration["Audience:Audience"].ToString(),
                new SigningCredentials(
                    new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Audience:Secret"].ToString())),
                    SecurityAlgorithms.HmacSha256),
                Configuration["Audience:OpenJwt"].ToString());

            var token = JwtToken.BuildJwtToken(claims, requirement, (AuthClientType)clientType);

            LogLoginDao.Insert(new t_log_login()
            {
                Phone = phone,
                Name = admin.Name,
                IP = Accessor.HttpContext.Connection.RemoteIpAddress.ToString(),
                CreateTime = DateTime.Now
            });

            return new JsonResult(new
            {
                Code = 0,
                Success = true,
                Msg = "登录成功",
                Data = admin,
                Token = token
            });
        }

        #endregion

        #region 获取权限

        /// <summary>
        /// 获取权限
        /// </summary>
        /// <param name="phone">电话号码</param>
        /// <returns>JSON结果集</returns>
        public JsonResult GetPermission(string phone)
        {
            var currentUser = AdminDao.QuerySingle(phone);
            var roles = currentUser.Result.Role.Split(',').ToList();
            var menuIds = AdminRoleMenuDao.QueryByWhere(w => roles.Contains(w.RoleId.ToString()), o => o.MenuId)
                .Result.Select(s => s.MenuId).Distinct().ToList();
            var menus = MenuDao.QueryByWhere(w => menuIds.Contains(w.ID), o => o.ID);

            var parentMenus = menus.Result.Where(w => "0".Equals(w.ParentId)).OrderBy(o => o.Sort);

            List<LayuiMenu> layuiMenus = new List<LayuiMenu>();
            foreach (var parentMenu in parentMenus)
            {
                var layuiMenu = new LayuiMenu
                {
                    Icon = parentMenu.Icon,
                    Title = parentMenu.Name,
                    Spread = false,
                    Name = parentMenu.Name,
                    Jump = parentMenu.Url,
                    List = GetSubMenus(menus.Result, parentMenu.ID)
                };

                layuiMenus.Add(layuiMenu);
            }

            return new JsonResult(new
            {
                Code = 0,
                Success = true,
                Msg = "获取权限成功",
                Data = layuiMenus
            });
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="menuAll"></param>
        /// <param name="parentId"></param>
        /// <returns>JSON结果集</returns>
        private List<LayuiMenu> GetSubMenus(List<t_menu> menuAll, string parentId)
        {
            List<LayuiMenu> layuiMenus;
            var subMenus = menuAll.Where(w => w.ParentId.Equals(parentId)).OrderBy(o => o.Sort);

            if (subMenus != null && subMenus.Count() > 0)
            {
                layuiMenus = new List<LayuiMenu>();

                foreach (var subMenu in subMenus)
                {
                    var layuiMenu = new LayuiMenu
                    {
                        Icon = subMenu.Icon,
                        Title = subMenu.Name,
                        Spread = false,
                        Name = subMenu.Name,
                        Jump = subMenu.Url,
                        List = GetSubMenus(menuAll, subMenu.ID)
                    };

                    layuiMenus.Add(layuiMenu);
                }
            }
            else
            {
                return new List<LayuiMenu>();
            }
            return layuiMenus;
        }

        #endregion

        #region 获取用户信息

        /// <summary>
        /// 获取用户信息
        /// </summary>
        /// <param name="id">用户ID</param>
        /// <returns>JSON结果集</returns>
        public JsonResult GetAdmin(string id)
        {
            var administor = AdminDao.QuerySingle(id);

            return new JsonResult(new
            {
                Code = 0,
                Success = true,
                Msg = "查询成功",
                Data = administor.Result
            });
        }

        #endregion

        #region 修改密码

        /// <summary>
        /// 修改密码
        /// </summary>
        /// <param name="id">用户ID</param>
        /// <param name="oldPassword">旧密码</param>
        /// <param name="newPassword">新密码</param>
        /// <returns>JSON结果集</returns>
        public JsonResult UpdatePassword(string id, string oldPassword, string newPassword)
        {
            var admin = AdminDao.QuerySingle(id).Result;

            if (admin == null)
            {
                return new JsonResult(new
                {
                    Code = 0,
                    Success = false,
                    Msg = "系统异常，请联系管理员。"
                });
            }

            AESCrypt aesCrypt = new AESCrypt();
            if (!oldPassword.Equals(aesCrypt.Decrypt(admin.PassWord)))
            {
                return new JsonResult(new
                {
                    Code = 0,
                    Success = false,
                    Msg = "您输入的旧密码不正确"
                });
            }

            if (newPassword.Trim().Length < 6)
            {
                return new JsonResult(new
                {
                    Code = 0,
                    Success = false,
                    Msg = "新密码长度过短"
                });
            }

            var result = AdminDao.Update(c => new t_admin() { PassWord = aesCrypt.Encrypt(newPassword) }, w => w.ID.Equals(id));

            return new JsonResult(new
            {
                Code = 0,
                Success = true,
                Msg = "密码修改成功"
            });
        }

        #endregion
    }
}